home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / ada / adaed-1.11 / adaed-1 / Adaed-1.11.0a / prserr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-07  |  37.3 KB  |  1,367 lines

  1. /*
  2.  * Copyright (C) 1985-1992  New York University
  3.  * 
  4.  * This file is part of the Ada/Ed-C system.  See the Ada/Ed README file for
  5.  * warranty (none) and distribution info and also the GNU General Public
  6.  * License for more details.
  7.  
  8.  */
  9. /********************************************************************
  10.  *                                    
  11.  *              *****************               
  12.  *              *  P R S E R R  
  13.  *              *****************             
  14.  *                                
  15.  *                 Written by                   
  16.  *               Brian Siritzky              
  17.  *                1983                 
  18.  *                                
  19.  ********************************************************************/
  20.  
  21. /********************************************************************/
  22.  
  23. /********************************************************************/
  24. #include "ada.h"
  25. #include "adalexprots.h"
  26. #include "actionprots.h"
  27. #include "pspansprots.h"
  28. #include "errsprots.h"
  29. #include "lookupprots.h"
  30. #include "prsutilprots.h"
  31. #include "recoverprots.h"
  32. #include "makecorrprots.h"
  33. #include "prserrprots.h"
  34.  
  35. static void get_poss_tok();
  36. static void get_next(int);
  37.  
  38. /*    
  39.  * Variables needed for scope and secondary recoveries
  40.  */
  41.  
  42. struct two_pool *closer_toksyms ;
  43. struct two_pool *closer_bottom ;
  44.  
  45. struct two_pool *POSS_TOK;
  46. /* struct prsstack **tokens; deleted on Sam's suggestion 12-11-84 */
  47. int    TOKSYMS[S_TOKSYMS], n_TOKSYMS;
  48. int    BACKUPTOKS = 0;
  49. int    MAX_CHECK = MIN_LEN ;
  50.  
  51. PCAND next_c, y, next_cand, CANDIDATES[C_BOUND];
  52. static PCAND tmp_cand,temp_cand;
  53. int    n_CANDIDATES[C_BOUND] ;
  54. int nps;
  55. int n_open_seq;
  56. int *open_seq;
  57. int n_closer_toksyms;
  58.  
  59. void prserr(struct prsstack *curtok)                            /*;prserr*/
  60. {
  61.  
  62.     /********************************************************************
  63.      *
  64.      * This routine is the syntactic error    recovery  routine.   It     at-
  65.      * tempts  to  correct    simple errors and when that is not possible,
  66.      * deletes tokens possibly to the left and to the right of the error
  67.      * point until the parse can safely resume.  The process is thus di-
  68.      * vided naturally into two  parts,  called  primary  and  secondary
  69.      * recovery.  Both primary and secondary recovery include efforts at
  70.      * "scope recovery": i.e.  the    closing     of  lexically    open  scopes
  71.      * through the insertion of one or more closer token sequences.     Ex-
  72.      * amples of such sequences are right parentheses, "END ;", and "END
  73.      * IF;".
  74.      * 
  75.      * Primary recovery consists of the simple corrections - merging to-
  76.      * kens,  substituting    a  token  (including a reserved word that is
  77.      * misspelled as an identifier), inserting a token, and     deleting  a
  78.      * token - along with scope recovery.
  79.      * 
  80.      * An attempt at simple correction at either the error token  or  at
  81.      * some parse stack element is called a trial.
  82.      * 
  83.      * For the first trial simple corrections are attempted at the token
  84.      * at which the error was detected (the error token), with the parse
  85.      * in the configuration obtaining just after  the  shifting  of     the
  86.      * previous  token. In order to back up to the succeeding trial, the
  87.      * top elements are peeled from the state and parse stacks, with the
  88.      * top element of the parse stack appended to the front of the input
  89.      * token sequence. Again attempts at simple correction are made. The
  90.      * process  is    repeated  until     the determined extent of the backup
  91.      * move has been accomplished.
  92.      * 
  93.      * The criterion by which the effectiveness of a  simple  correction
  94.      * candidate is measured is the distance it allows the parse to pro-
  95.      * gress into the forward context (up to  MAX_LOOK_AHEAD  =  25     to-
  96.      * kens).   During  the     simple correction trials we gather together
  97.      * the CANDIDATES that allow the parse    to  progress  the  furthest,
  98.      * provided  that  an  advance of at least MIN_CHECK is accomplished
  99.      * (if not, then CANDIDATES is empty and simple     correction  fails).
  100.      * If  CANDIDATES is not empty, it is pruned in accordance with cer-
  101.      * tain restrictions described below, and then one of them is chosen
  102.      * as the appropriate correction provided that a condition described
  103.      * below is satisfied.
  104.      * 
  105.      * No attempt is made to delete or substitute for a nonterminal.
  106.      * 
  107.      * If no simple correction is chosen, scope recovery is attempted at
  108.      * each     point    at  which  simple  recovery was attempted. The scope
  109.      * recovery procedure determines whether the insertion of a sequence
  110.      * of  scope  closers  allows the parse to progress MIN_LEN distance
  111.      * into the forward context.  If  so,  this  multiple  insertion  is
  112.      * chosen as the correction candidate.
  113.      * 
  114.      * If scope recovery also fails, then secondary recovery is invoked.
  115.      * The    parse  is  restored  to the configuration obtaining upon en-
  116.      * trance to PRSERR, and each parse stack element is tested - in se-
  117.      * quence from the top - to see whether parsing can resume from that
  118.      * point, perhaps with the inclusion of one or more closer token se-
  119.      * quences.  The  extent  of  the  advance required in order for the
  120.      * parse to be regarded as successfully     resumed  depends  upon     the
  121.      * current token, but is at least MIN_LEN.
  122.      * 
  123.      * If secondary recovery at the current token does not    succeed,  it
  124.      * is  ignored    and  the next one obtained and the same check is re-
  125.      * peated. Eventually, there must be an input for  which  the  parse
  126.      * can    continue, because the end of file token, EOFT, is compatible
  127.      * with a state on the state stack.
  128.      * 
  129.      * When the recovery point is found,  control  is  returned  to     the
  130.      * parser.  It is assured that parsing can continue beyond the error
  131.      * token.
  132.      * 
  133.      ********************************************************************/
  134.  
  135.     /* PARSE STACK and BINARY TUPLE STRUCTURES */
  136.     typedef struct two_pool *TUPLE;
  137.  
  138.  
  139.     struct prsstack *ERROR_TOKEN;
  140.     struct prsstack *oldprevtok;/* Saved for scope and secondary recovery */
  141.     struct prsstack *tmp_ps;
  142.  
  143.     TUPLE STATE_STACK = NULL;
  144.     TUPLE prs_toks = NULL;    /* Used to determine the no of */
  145.     TUPLE tmp_tp;            /* trials to be performed */
  146.     /* Used for freeing storage */
  147.     TUPLE prs_stack_syms = NULL;
  148.  
  149.     int pb;            /* Used as a flag to check for a parse block */
  150.     int threshold,        /* Used to prune candidates */
  151.     exists;        /* Flag used in list searching */
  152.  
  153.     short trials,        /* Number of trials performed    */
  154.       j, r, trial,
  155.       i,            /* Loop and auxilliary        */
  156.       bk, cc, x, si ;
  157.  
  158.     int n_PARSE_STACK;
  159.     int save_n_TOKSYMS ;
  160.     struct two_pool *states;
  161.  
  162.     int        n_single_cand_modes, total_CANDIDATES;
  163.     int        n_STATE_STACK, n_sta_stack;
  164.  
  165.     ERROR_TOKEN = copytoken (curtok);
  166.     MAX_CHECK = MIN_LEN;
  167.  
  168.     /* ERR_MSGS = NULL ; CLOSER_TOKSYMS = NULL ; */
  169.  
  170.     copystack (sta_stack, &STATE_STACK, &n_sta_stack);
  171.     /* save for scope and secondary recovery */
  172.     if (PREVTOK != NULL)
  173.         oldprevtok = copytoken (PREVTOK);
  174.  
  175.     n_STATE_STACK = n_sta_stack;
  176.  
  177.     BACKUPTOKS = 0;
  178.  
  179.     get_next (MAX_LOOK_AHEAD);
  180.  
  181.     /* prs_stack_syms := [r(1) : r in PRS_STACK];            
  182.      * Loop over PRS_STACK, collecting the symbols in a list  
  183.      * headed by prs_stack_syms. While doing this, count up the 
  184.      * number of elements in the parse stack, keeping this in  
  185.      * n_PARSE_STACK and nps                   
  186.      */
  187.  
  188.     n_PARSE_STACK = 0;
  189.  
  190.     if ((tmp_ps= prs_stack) == NULL)/* Check for empty stacks */
  191.         prs_stack_syms = NULL;
  192.     else {                /* otherwise copy the list */
  193.         /* Treat the first element as a special case */
  194.         tmp_tp = prs_stack_syms = TALLOC ();
  195.         tmp_tp -> link = NULL;
  196.         tmp_tp -> val.state = tmp_ps -> symbol;
  197.         n_PARSE_STACK = 1;
  198.         /* Loop over the rest of the stack */
  199.         while (tmp_ps -> prev != NULL) {
  200.             tmp_tp -> link = TALLOC ();
  201.             tmp_tp = tmp_tp -> link;
  202.             tmp_ps = tmp_ps -> prev;
  203.             tmp_tp -> val.state = tmp_ps -> symbol;
  204.             n_PARSE_STACK++;
  205.         }            /* while */
  206.         tmp_tp -> link = NULL;
  207.     }                /* else */
  208.     nps = n_PARSE_STACK;
  209.  
  210.     /* * TOKSYMS := [t(1) : t in TOKENS];             
  211.      * Loop over TOKENS, collecting the symbols in a list    
  212.      * The integer tokind is a count of the number of     
  213.      * elements in the array tokens.              
  214.      *
  215.      * Note that tokens[tokind] is the next token, so we must
  216.      * reverse the order of TOKSYMS                            
  217.      */
  218.  
  219.     /* Put the current token at the top of the token stack */
  220.     tokens[tokind = (tokind + 1) % toksiz] = curtok;
  221.     i = 0;
  222.     j = tokbottom;
  223.  
  224.     for (;;) {
  225.         TOKSYMS[i] = tokens[j]->symbol;
  226.         if (j == tokind)
  227.             break;
  228.         j = (j + 1) % toksiz;
  229.         i++;
  230.     }
  231.  
  232.     save_n_TOKSYMS    = n_TOKSYMS = (toksiz + tokind - tokbottom) % toksiz;
  233.     /*
  234.     for (i = 0; i <= tokind; i++)
  235.     TOKSYMS[i] = tokens[i] -> symbol;
  236.  
  237.     n_TOKSYMS = tokind;
  238.     */
  239.     dump_toksyms ("At creation");
  240.  
  241.     /******************************************************************* 
  242.      *
  243.      *                    S I M P L E    R E C O V E R Y            
  244.      *           
  245.      *******************************************************************/
  246.  
  247.     /*    Simple Recovery begins here     */
  248.  
  249.     /* Determine number of trials to be performed.  */
  250.     prs_toks = TALLOC ();
  251.     prs_toks -> val.state = curtok -> symbol;
  252.     prs_toks -> link = NULL;
  253.  
  254.     /* trials = (nps>0) ? nps : 1 ; */
  255.     trials = (n_sta_stack>0) ? n_sta_stack : 1 ;
  256.  
  257.     states = TALLOC ();
  258.     states -> link = NULL;
  259.  
  260.     /* for (j = nps; j >= 1; j--) */
  261.     for (j = n_sta_stack; j >= 2; j--) {
  262.         int    jj;
  263.         /* prs_stack_syms(j) is at position (nps - j)  in the linked list.
  264.          * For this reason we need to follow the links this many times
  265.          */
  266.         /* jj = nps - j + 1; */
  267.         jj = n_sta_stack - j + 1;
  268.         tmp_tp = prs_stack_syms;
  269.         while (jj-- > 1)
  270.             tmp_tp = tmp_tp -> link;
  271.  
  272.         r = tmp_tp -> val.state;    /* r := prs_stack_syms(j) */
  273.  
  274. #ifdef DEBUG
  275.         if (trcopt) {
  276.             fprintf(errfile,"j = %d     n_sta_stack = %d  r = %d\n",
  277.               j,n_sta_stack,r);
  278.         }
  279. #endif
  280.         /* dump_stack(prs_toks); */
  281.  
  282.         /* Check whether it is possible to parse past symbol
  283.          *    and through the error token.            
  284.          *
  285.          *    if forall s in SHIFT_STATES(r) | prs_block(s, prs_toks)
  286.          *    then
  287.          *        trials := nps - j + (if is_terminal(r) then 2 else 1 end);
  288.          *        quit;
  289.          *    end if;
  290.          */
  291.         pb = TRUE;        /* Assume that the parse will block */
  292.         /* Loop through SHIFT_STATES(r). This is the array SHIFT_STATES from
  293.          * position SHIFT_STATE_INDEX(r-1) to SHIFT_STATE_INDEX(r) - 1
  294.          * Each time check if the parse blocks, pb. If it does not then end the
  295.          * testing.
  296.          */
  297.         for (si = SHIFT_STATE_INDEX[r - 1];
  298.           ((si <= (SHIFT_STATE_INDEX[r] - 1)) && pb);
  299.           si++)
  300.         {
  301.             states -> val.state = SHIFT_STATE[si];
  302.             pb = pb && prs_block (states, prs_toks);
  303.  
  304. #ifdef DEBUG
  305.             if (trcopt)
  306.                 fprintf(errfile,"state: %d     prsblock: %d\n",
  307.                   states->val.state, prs_block(states,prs_toks) );
  308. #endif
  309.         }
  310.  
  311.         if (pb) {            /*  If the parse blocks then terminate    */
  312.             /*trials = 1 + nps - j + (is_terminal (r - 1) ? 2 : 1);*/
  313.             trials = 1 + n_sta_stack - j + (is_terminal (r) ? 2 : 1);
  314.             break;        /* Outer loop */
  315.         }
  316.  
  317.         tmp_tp = TALLOC ();
  318.         tmp_tp -> link = prs_toks;
  319.         tmp_tp -> val.state = r;
  320.         prs_toks = tmp_tp;
  321.  
  322.     }                /* end for */
  323.  
  324.     if (nps == 0)
  325.         trials = 1;    /* To deal with empty parse stacks */
  326. #ifdef DEBUG
  327.     if (trcopt)
  328.         fprintf(errfile,"trials = %d\n",trials);
  329. #endif
  330.  
  331.     for (trial = 1; trial <= trials; trial++) {
  332.         /*    Attempt simple recovery at token backed up to.     */
  333. #ifdef DEBUG
  334.         if (trcopt) {
  335.             fprintf(errfile,"Backup Recovery, trial number is: %d\n",trial);
  336.             fprintf(errfile,"STATE STACK:\n");
  337.             dump_stack(sta_stack);
  338.             fprintf(errfile,"PARSE STACK:\n");
  339.             dump_prssyms(prs_stack_syms);
  340.             fprintf(errfile,"TOKENS:\n");
  341.             dump_toksyms("");
  342.         }
  343. #endif
  344.  
  345.         /* Form set of candidates for insertion and substitution. */
  346.  
  347.         get_poss_tok ();
  348.  
  349.         /* Make insertion test.   */
  350.  
  351.         try_insertion ();
  352.  
  353.         /* Attempt substitution for current token */
  354.  
  355.         try_substitution ();
  356.  
  357.         /* Try merging tokens. */
  358.  
  359.         if (trial == 1)
  360.             try_merge (curtok, nexttok);
  361.         else
  362.             if (trial == 2)
  363.                 try_merge (PREVTOK, curtok);
  364.  
  365.         /* Check whether parsing can resume with the next token. */
  366.  
  367.         try_deletion ();
  368.  
  369.         /* Now we peel off the top state and try again.           
  370.          * Put the "token" (terminal or nonterminal) for previous state on 
  371.          * the list of tokens, and increase backuptoks accordingly.       
  372.          */
  373.  
  374.         tmp_tp = sta_stack;
  375.         sta_stack = sta_stack -> link;
  376.         n_sta_stack--;
  377.  
  378.         tmp_tp = prs_stack_syms;
  379.         if (prs_stack != NULL) {
  380.             TOKSYMS[++n_TOKSYMS] = prs_stack_syms -> val.state;
  381.             prs_stack_syms = prs_stack_syms -> link;
  382.         }
  383.         BACKUPTOKS++;
  384.  
  385.     }                /* for */
  386.  
  387.  
  388.     /* Form misspelling candidates by applying string distance test in cases
  389.      *   where a reserved word to be substituted for an identifier.     
  390.      */
  391.  
  392.     if (0 && CANDIDATES[SUBST] != NULL) {
  393. #ifdef DEBUG
  394.         if (trcopt)
  395.             fprintf (errfile, "CANDIDATES[SUBST] != NULL, (#=%d)\n",
  396.                 n_CANDIDATES[SUBST]);
  397. #endif
  398.         /*  spell_substs := {[u, v, w] in CANDIDATES(SUBST) |
  399.          *         is_reserved(u) and v = ID_SYM 
  400.          *        and spell(namelist(u), namelist(
  401.          *         (w = 0 ? curtok : PRS_STACK(nps - w + 1) )(2)))};
  402.          *
  403.          *   Note : u == token_sym, v == backup_toks, w == t3
  404.          *
  405.          *   Loop over the list headed by CANDIDATES[SUBST], selecting
  406.          *  all those elements which satisfy the above conditions
  407.          *
  408.          *    The spell function used here is a less accurate measure than the
  409.          *  SETL version. It returns an integer value in the range [0,3],
  410.          *  where 0, 1 & 2 imply misspellings.
  411.          */
  412.         nps = stack_count(prs_stack) ;
  413.         next_c = CANDIDATES[SUBST];
  414.         while (next_c != NULL) {
  415.             short   symb;    /* Utility variable */
  416.             PCAND    follow_c ;
  417.  
  418.             follow_c = next_c-> next ;
  419.  
  420.             /* Calculate the word to be compared to according to
  421.              *        symb = (w==0)?curtok : prs_stack(nps -w + 1)
  422.              */
  423.  
  424.             if (next_c -> backup_toks == 0)
  425.                 symb = curtok -> symbol;
  426.             else {            /* PRSSTACK[nps-w-1].symbol */
  427.                 int kk = nps - next_c->backup_toks ;
  428.  
  429.                 tmp_ps = prs_stack;
  430.                 while(--kk)
  431.                     tmp_ps = tmp_ps -> prev;
  432.                 symb = tmp_ps -> symbol;
  433.             }
  434.  
  435.             if ( (is_reserved (next_c -> token_sym))
  436.               && (next_c -> t3 == ID_SYM)
  437.               && ((spell (TOKSTR (next_c -> token_sym), TOKSTR (symb))) < 3 ) )
  438.             {
  439.                 /* Add it to the list of SPELL_SUBSTs. */
  440.  
  441.                 next_c-> next = CANDIDATES[SPELL_SUBST] ;
  442.                 CANDIDATES[SPELL_SUBST] = next_c ;
  443.                 n_CANDIDATES[SPELL_SUBST]++;
  444.                 n_CANDIDATES[SUBST]--;
  445.             }
  446.  
  447.             next_c = follow_c ;
  448.         }
  449.  
  450.     }
  451. #ifdef DEBUG
  452.     if (trcopt) {
  453.         fprintf(errfile,"Candidates BEFORE pruning\n");
  454.         dump_cand();
  455.     }
  456. #endif
  457.  
  458.     /* The correction candidates now include only those that have checked
  459.      * the furthest distance into the forward context.
  460.      * Prune this set by applying the preferences and restrictions relevant 
  461.      * in each case.
  462.      */
  463.  
  464.     /* If a long parse check has been achieved, set threshold to true.  */
  465.  
  466.     threshold = (MAX_CHECK >= (MIN_LEN + 3));
  467.  
  468.     /*  (for y = CANDIDATES(x)) */
  469.  
  470.     for (x = DELETE; x <= SPELL_SUBST; x++)
  471.     {
  472.         y = CANDIDATES[x];
  473.  
  474.         if (y == NULL)        /* Check for null candidate list */
  475.             continue;
  476.  
  477.         switch (x) {
  478.  
  479.         case DELETE:
  480.  
  481.             /* Remove all reserved word deletions if another deletion exists
  482.              * and all such deletions if below the threshold            
  483.              */
  484.  
  485.             next_cand = CANDIDATES[DELETE];
  486.             exists = FALSE;
  487.             while ((next_cand != NULL) && (!exists)) {
  488.                 exists = exists && (next_cand -> token_sym > RESERVED_SYMS);
  489.                 next_cand = next_cand -> next;
  490.             }
  491.  
  492.             if ((!threshold) || exists) {
  493.                 /*  y -:= {[token_sym,-,-] in y | is_reserved(token_sym) }
  494.                  *  This is achieved by looping over the list headed by y
  495.                  *  and deleting those elements which satisfy the condition 
  496.                  */
  497.                 next_cand = CANDIDATES[x];
  498.                 n_CANDIDATES[x] = 0;
  499.                 CANDIDATES[x] = NULL;
  500.                 while (next_cand != NULL) {
  501.                     /* there are more candidates */
  502.                     tmp_cand = next_cand -> next;
  503.                     if (!is_reserved (next_cand -> token_sym)) {
  504.                         /* Add it to the front of the list  */
  505.                         n_CANDIDATES[x]++;
  506.                         next_cand -> next = CANDIDATES[x];
  507.                         CANDIDATES[x] = next_cand;
  508.                     }
  509.                     next_cand = tmp_cand;
  510.                 }
  511.             }
  512.  
  513.             /* Prefer deletion closest to error token.    */
  514.  
  515.             if (y != NULL) {
  516.                 /* bk := min/{t(2) : t in y}; */
  517.                 next_cand = y;
  518.                 bk = next_cand -> backup_toks;
  519.                 next_cand = next_cand -> next;
  520.                 while (next_cand != NULL) {
  521.                     bk = MIN (bk, next_cand -> backup_toks);
  522.                     next_cand = next_cand -> next;
  523.                 }
  524.  
  525.                 n_CANDIDATES[x] = 0;
  526.                 next_cand = CANDIDATES[x];
  527.                 CANDIDATES[x] = NULL;
  528.                 while (next_cand != NULL) {
  529.                     /* there are more candidates */
  530.                     tmp_cand = next_cand -> next;
  531.                     if (next_cand -> backup_toks == bk) {
  532.                         next_cand -> next = CANDIDATES[x];
  533.                         CANDIDATES[x] = next_cand;
  534.                         n_CANDIDATES[x]++;
  535.                     }
  536.  
  537.                     next_cand = tmp_cand;
  538.                 }
  539.             }
  540.             break;
  541.  
  542.         case INSERT:
  543.  
  544.             /* Remove all insertions of reserved words if below threshold */
  545.  
  546.             if (!threshold) {
  547.                 /* y -:= {[token_sym,-,-] in y | is_reserved(token_sym) }     
  548.                  * This is achieved by looping over the list headed by y   
  549.                  * and deleting those elements which satisfy the condition 
  550.                  */
  551.                 n_CANDIDATES[x] = 0;
  552.                 next_cand = CANDIDATES[x];
  553.                 CANDIDATES[x] = NULL;
  554.                 while (next_cand != NULL) {
  555.                     /* there are more candidates */
  556.                     tmp_cand = next_cand -> next;
  557.                     if (!is_reserved (next_cand -> token_sym)) {
  558.                         next_cand -> next = CANDIDATES[x];
  559.                         CANDIDATES[x] = next_cand;
  560.                         n_CANDIDATES[x]++;
  561.                     }
  562.                     next_cand = tmp_cand;
  563.                 }
  564.             }
  565.  
  566.             /* Prefer insertions closest to error token. */
  567.  
  568.             if (CANDIDATES[x] != NULL) {
  569.                 /* bk := min/{t(3) : t in y}; */
  570.                 next_cand = y;
  571.                 bk = next_cand -> backup_toks;
  572.                 next_cand = next_cand -> next;
  573.                 while (next_cand != NULL) {
  574.                     bk = MIN (bk, next_cand -> backup_toks);
  575.                     next_cand = next_cand -> next;
  576.                 }
  577.                 /* y := {[-,backup_toks,-] in y | backup_toks = bk) }       
  578.                  *
  579.                  * This is achieved by looping over the list headed by y   
  580.                  * and deleting those elements which satisfy the condition
  581.                  * While doing this, check if there are any elements  that 
  582.                  * satisfy the condition            
  583.                  *        (token_sym in ALWAYS_PREFERRED_SYMS) 
  584.                  * If there are any they can be used to further prune the  
  585.                  * list. A flag 'exists' will be used for this purpose.
  586.                  */
  587.  
  588.                 n_CANDIDATES[x] = 0;
  589.                 next_cand = CANDIDATES[x];
  590.                 CANDIDATES[x] = NULL;
  591.                 exists = FALSE;
  592.                 /* Assume none in ALWAYS_PREFERRED_SYMS */
  593.                 while (next_cand != NULL) {
  594.                     /* there are more candidates */
  595.                     tmp_cand = next_cand -> next;
  596.                     if (next_cand -> backup_toks == bk) {
  597.                         exists = exists
  598.                           || in_ALWAYS_PREFERRED_SYMS (next_cand -> token_sym);
  599.                         next_cand -> next = CANDIDATES[x];
  600.                         CANDIDATES[x] = next_cand;
  601.                         n_CANDIDATES[x]++;
  602.                     }
  603.                     next_cand = tmp_cand;
  604.                 }
  605.             }
  606.  
  607.             /*     Apply preferred insertions (if any exist)
  608.              *
  609.              *    pi := {[u, v, w] in y | u in ALWAYS_PREFERRED_SYMS};
  610.              *    if (pi != {}) y = pi;
  611.              */
  612.  
  613.             if (exists) {        /* then prune the list accordingly */
  614.                 /* y := {[token_sym,-,-] in y | token_sym in              
  615.                  *        ALWAYS_PREFERRED_SYMS }               
  616.                  * This is achieved by looping over the list headed by y    
  617.                  * and deleting those elements which satisfy the condition  
  618.                  */
  619.  
  620.                 n_CANDIDATES[x] = 0;
  621.                 next_cand = CANDIDATES[x];
  622.                 CANDIDATES[x] = NULL;
  623.                 while (next_cand != NULL) {
  624.                     /* there are more candidates */
  625.                     tmp_cand = next_cand -> next;
  626.                     if (in_ALWAYS_PREFERRED_SYMS (next_cand -> token_sym)) {
  627.                         next_cand -> next = CANDIDATES[x];
  628.                         CANDIDATES[x] = next_cand;
  629.                         n_CANDIDATES[x]++;
  630.                     }
  631.                     next_cand = tmp_cand;
  632.                 }
  633.             }
  634.             break;
  635.  
  636.         case SUBST:
  637.  
  638.             /*         Apply preferred substitutions 
  639.              * 
  640.              *    Check to see whether there are any elements which satisfy   
  641.              *    either of the conditions        
  642.              *            token_sym in PREFERRED_FOR_SYMS{v}
  643.              *           or    token_sym = ID_SYM and is_reserved(v) 
  644.              *    If at least one is found then set y to be ps, where ps is   
  645.              *
  646.              *        ps := {[u, v, w] in y | u in PREFERRED_FOR_SYMS{v}    
  647.              *                or (u = ID_SYM and is_reserved(v))};        
  648.              *
  649.              *    This is achieved by looping over the list headed by y    
  650.              *    and deleting those elements which satisfy the condition
  651.              */
  652.  
  653.             /* check for existence */
  654.  
  655.             next_cand = CANDIDATES[x];
  656.             exists = FALSE; /* Assume none */
  657.             while ((next_cand != NULL) && (!exists)) {
  658.                 /* there are more candidates */
  659.                 exists = exists
  660.                   || in_PREFERRED_FOR_SYMS( next_cand -> t3,
  661.                    next_cand -> token_sym)
  662.                   || ((next_cand -> token_sym == ID_SYM)
  663.                   && (is_reserved (next_cand -> t3)));
  664.                 next_cand = next_cand -> next;
  665.             }
  666.  
  667.             /* If some exist then y is set to be those only */
  668.  
  669.             if (exists) {
  670.                 n_CANDIDATES[x] = 0;
  671.                 next_cand = CANDIDATES[x];
  672.                 CANDIDATES[x] = NULL;
  673.                 while (next_cand != NULL) {
  674.                     /* there are more candidates */
  675.                     temp_cand = next_cand -> next;
  676.                     if ( in_PREFERRED_FOR_SYMS( next_cand -> t3,
  677.                       next_cand -> token_sym )
  678.                       || ((next_cand -> token_sym == ID_SYM)
  679.                       && is_reserved (next_cand -> t3)))
  680.                     {
  681.                         next_cand -> next = CANDIDATES[x];
  682.                         CANDIDATES[x] = next_cand;
  683.                         n_CANDIDATES[x]++;
  684.                     }
  685.                     next_cand = temp_cand;
  686.                 }
  687.             }
  688.             else if (!threshold) {        /* None exist */
  689.                 /* Remove all substitutions involving reserved words if below    
  690.                  * the threshold.                        
  691.                  */
  692.                 /* y -:= {[u, v, w] in y |    
  693.                      *             is_reserved(u) or is_reserved(v)};  
  694.                  */
  695.  
  696.                 n_CANDIDATES[x] = 0;
  697.                 next_cand = CANDIDATES[x];
  698.                 CANDIDATES[x] = NULL;
  699.                 while (next_cand != NULL) {
  700.                     temp_cand = next_cand -> next;
  701.                     if (!((is_reserved (next_cand -> t3))
  702.                       || (is_reserved (next_cand -> token_sym))) )
  703.                     {
  704.                         next_cand -> next = CANDIDATES[x];
  705.                         CANDIDATES[x] = next_cand;
  706.                         n_CANDIDATES[x]++;
  707.                     }
  708.                     next_cand = temp_cand;
  709.                 }
  710.             }
  711.  
  712.             /* Prefer substitutions closest to error token. */
  713.  
  714.             if (CANDIDATES[x] != NULL) {
  715.                 /* bk := min/{t(3) : t in y}; */
  716.                 next_cand = y;
  717.                 bk = next_cand -> backup_toks;
  718.                 next_cand = next_cand -> next;
  719.                 while (next_cand != NULL) {
  720.                     bk = MIN (bk, next_cand -> backup_toks);
  721.                     next_cand = next_cand -> next;
  722.                 }
  723.  
  724.                 n_CANDIDATES[x] = 0;
  725.                 next_cand = CANDIDATES[x];
  726.                 CANDIDATES[x] = NULL;
  727.                 while (next_cand != NULL) {
  728.                     /* there are more candidates */
  729.                     temp_cand = next_cand -> next;
  730.                     if (next_cand -> backup_toks == bk) {
  731.                         next_cand -> next = CANDIDATES[x];
  732.                         CANDIDATES[x] = next_cand;
  733.                         n_CANDIDATES[x]++;
  734.                     }
  735.                     next_cand = temp_cand;
  736.                 }
  737.             }
  738.             break;
  739.  
  740.         case SPELL_SUBST:
  741.  
  742.             /* Prefer closest to error token. */
  743.  
  744.             /* bk := min/{t(3) : t in y}; */
  745.  
  746.             next_cand = y;
  747.             bk = next_cand -> backup_toks;
  748.             next_cand = next_cand -> next;
  749.             while (next_cand != NULL) {
  750.                 bk = MIN (bk, next_cand -> backup_toks);
  751.                 next_cand = next_cand -> next;
  752.             }
  753.  
  754.             /*         y := {[-,-,t3] in y | t3=bk }            
  755.              * This is achieved by looping over the list headed by y   
  756.              * and deleting those elements which satisfy the condition 
  757.              */
  758.  
  759.             if (CANDIDATES[x] != NULL) {
  760.                 n_CANDIDATES[x] = 0;
  761.                 next_cand = CANDIDATES[x];
  762.                 CANDIDATES[x] = NULL;
  763.                 while (next_cand != NULL) {
  764.                     /* there are more candidates */
  765.                     temp_cand = next_cand -> next;
  766.                     if (next_cand -> backup_toks == bk) {
  767.                         next_cand -> next = CANDIDATES[x];
  768.                         CANDIDATES[x] = next_cand;
  769.                         n_CANDIDATES[x]--;
  770.                     }
  771.                     next_cand = temp_cand;
  772.                 }
  773.             }
  774.             break;
  775.  
  776.         case MERGE:
  777.  
  778.             break;
  779.  
  780.         }            /* switch */
  781.  
  782.     }                /* for */
  783. #ifdef DEBUG
  784.     if (trcopt) {
  785.         fprintf(errfile,"Candidates AFTER pruning:\n");
  786.         dump_cand();
  787.     }
  788. #endif
  789.  
  790.  
  791.     /* For each mode - merge, spelling, insertion, substitution, deletion -
  792.      * there are zero or more correction candidates.  
  793.      * If one or mode has exactly one correction candidate, then one of those
  794.      * candidates is chosen.
  795.      * 
  796.      * If no mode has a single candidate, then a simple correction candidate 
  797.      * is only chosen if the long check distance has been achieved 
  798.      *            (MAX_CHECK >= MIN_LEN + 3).
  799.      * 
  800.      * The preference order among the correction modes is : merge, spelling,
  801.      * insertion, deletion, substitution.
  802.      */
  803.  
  804.     /* Calculate the number of single_cand_modes     */
  805.     /* and the total number of CANDIDATES         */
  806.  
  807.     n_single_cand_modes = 0;
  808.     total_CANDIDATES = 0;
  809.  
  810.     for (cc = DELETE; cc <= SPELL_SUBST; cc++) {
  811.         if (n_CANDIDATES[cc] == 1)
  812.             n_single_cand_modes++;
  813.         total_CANDIDATES += n_CANDIDATES[cc];
  814.     }
  815.  
  816.     if (n_single_cand_modes > 0) {
  817.         /* Apply one final preference rule where there remains a single 
  818.          *    deletion and a single insertion candidate - prefer deletion of 
  819.          *    operator or punctuation symbol to insertion of such a symbol.  
  820.          */
  821.         if ((n_CANDIDATES[DELETE] == 1)
  822.           && ((n_CANDIDATES[INSERT]) == 1)
  823.           && is_operator (CANDIDATES[DELETE] -> token_sym)
  824.           && is_operator (CANDIDATES[INSERT] -> token_sym))
  825.         {
  826.             /* Set CANDIDATES[INSERT] to NULL and dispose of the list */
  827.             CANDIDATES[INSERT] = NULL;
  828.             n_CANDIDATES[INSERT] = 0;
  829.             n_single_cand_modes--;
  830.             total_CANDIDATES--;
  831.         }
  832.  
  833.         /* Set all CANDIDATES which have more than 1 element to NULL    
  834.          * and dispose of their lists                        
  835.          */
  836.  
  837.         for (cc = DELETE; cc <= SPELL_SUBST; cc++)
  838.             if (n_CANDIDATES[cc] > 1) {
  839.                 CANDIDATES[cc] = NULL;
  840.                 n_CANDIDATES[cc] = 0;
  841.             }
  842.  
  843.     }                /* if */
  844.  
  845.     if ((n_single_cand_modes > 0) || ((total_CANDIDATES > 0) && threshold)) {
  846.         make_correction (STATE_STACK);
  847.         return;
  848.     }
  849.  
  850.     /*  Primary recovery has failed if we reach this point. 
  851.      *  Reset parse configuration for scope recovery.    
  852.      */
  853.  
  854.     copystack (STATE_STACK, &sta_stack, &n_STATE_STACK);
  855.     /*  TOKSYMS(n_TOKENS + 1 .. ) := []; */
  856.     n_TOKSYMS = save_n_TOKSYMS ;
  857.     BACKUPTOKS = 0;
  858.  
  859.     /************************************************************************
  860.      *                                      
  861.      *        E N D     O F     P R I M A R Y    R E C O V E R Y           
  862.      *                                    
  863.     ************************************************************************/
  864.  
  865.     /************************************************************************
  866.      *                                      
  867.      *                    Scope recovery 
  868.      *                                    
  869.     ************************************************************************/
  870.  
  871.     /* SCOPE */
  872.     {
  873.  
  874.         int     j;
  875.         struct prsstack *prstmp;
  876.         struct two_pool *tuptmp;
  877.         struct two_pool *statmp;
  878.         struct tok_loc *prev_tok_loc;
  879.         /* struct tok_loc *prev_tok_loc = &PREVTOK->ptr.token->loc; */
  880.  
  881.         if (PREVTOK != NULL)
  882.             prev_tok_loc = &PREVTOK->ptr.token->loc;
  883.  
  884.         /*    Allocate an array the size of the parse stack */
  885.         open_seq = (int *)malloc((unsigned) (nps * sizeof(int)));
  886.  
  887. #ifdef DEBUG
  888.         if (trcopt)
  889.             fprintf(errfile,"SCOPE OPENERS = \n");
  890. #endif
  891.         for (n_open_seq = 0,j = nps, prstmp = prs_stack; prstmp != NULL;
  892.           prstmp = prstmp->prev, j--) {
  893.             if (is_opener(prstmp->symbol)) {
  894.                 open_seq[n_open_seq++] = j;
  895. #ifdef DEBUG
  896.                 if (trcopt)
  897.                     fprintf(errfile,"[ %s %d ] ",TOKSTR(prstmp->symbol),j);
  898. #endif
  899.             }
  900.         }
  901. #ifdef DEBUG
  902.         if (trcopt)
  903.             fprintf(errfile,"\n");
  904. #endif
  905.  
  906.         /* for debugging purposes try one less trial */
  907.         trials-- ;
  908.  
  909.  
  910.         closer_toksyms = NULL;
  911.         closer_bottom = NULL;
  912.  
  913.         for (trial = 1 ; trial <= trials ; trial ++ ) {
  914. #ifdef DEBUG
  915.             if (trcopt)
  916.                 fprintf(errfile,"Scope Recovery Trial = %d\n",trial);
  917. #endif
  918.             if (scope_recovery(n_STATE_STACK,0,open_seq)) {
  919.                 for (tuptmp = closer_toksyms; tuptmp != NULL;
  920.                   tuptmp = tuptmp->link)
  921.                 {
  922.                     prstmp = PRSALLOC();
  923.                     prstmp->ptr.token = TOKALLOC();
  924.                     prstmp->symbol =prstmp->ptr.token->index =tuptmp->val.state;
  925.                     prstmp->ptr.token->loc.line = prev_tok_loc->line;
  926.                     prstmp->ptr.token->loc.col = prev_tok_loc->col;
  927.                     ADDTOTOP(prstmp);
  928.                 }
  929.                 /* if (closer_toksyms != NULL)
  930.                  * TFREE(closer_toksyms,closer_bottom);
  931.                  */
  932.                 n_closer_toksyms = 0 ;
  933.                 return;
  934.             }
  935.             /* if (closer_toksyms != NULL)
  936.              *    TFREE(closer_toksyms,closer_bottom);
  937.              */
  938.             n_closer_toksyms = 0 ;
  939.             /*    Back up for the next trial */
  940.  
  941.             if (trial == trials)
  942.                 break;
  943.  
  944.             statmp = sta_stack;
  945.             sta_stack = sta_stack->link;
  946.             TFREE(statmp,statmp);
  947.             n_STATE_STACK -- ;
  948.  
  949.             prstmp = prs_stack;
  950.             prs_stack = prs_stack->prev;
  951.             nps-- ;
  952.  
  953.             ADDTOTOP(prstmp);
  954.  
  955.             TOKSYMS[++n_TOKSYMS] = prstmp->symbol;
  956.  
  957.             BACKUPTOKS++;
  958.  
  959.             prev_tok_loc = RLOC(prs_stack);
  960.         }
  961.  
  962.         /*    To get here scope recovery has failed, try other recoveries */
  963.  
  964.         /*  First restore the parse configuration for secondary recovery */
  965.         copystack(STATE_STACK,&sta_stack,&n_sta_stack) ;
  966.  
  967.         for (trial = 1 ; trial < trials ; trial ++) {
  968.             struct prsstack *tmp_ps ;
  969.  
  970.             tmp_ps = tokens[tokind];
  971.             n_TOKSYMS -- ;
  972.             TOKMINUS ;
  973.             tmp_ps->prev = prs_stack ;
  974.             prs_stack = tmp_ps ;
  975.             nps ++ ;
  976.         }
  977.  
  978.         PREVTOK = oldprevtok ;
  979.         BACKUPTOKS = 0 ;
  980.     }
  981.  
  982.     /************************************************************************
  983.      *                                      
  984.      *                    Secondary recovery 
  985.      *                                    
  986.      ************************************************************************/
  987.     /*SEC*/
  988.  
  989.     /* Now try secondary recoveries.    
  990.      * First try deleting the error token and some sequence of tokens in the 
  991.      * forward context - stop at a beacon symbol.    
  992.      */
  993.     {
  994. #define sec_check    MIN_LEN
  995.  
  996.         char    tmp_str[500],
  997.         err_msgs[500];
  998.         int        equal;
  999.         int        nst;
  1000.         int        n_stack_del_syms;
  1001.         int        t, kk, j, k;
  1002.         int       *stack_delete_syms;
  1003.         struct tok_loc  leftt,
  1004.         rightt;
  1005.  
  1006.         err_msgs[0] = '\0' ; /* initialize to null string */
  1007.  
  1008.         for (k = 1; k <= MAX_LOOK_AHEAD - (MIN_LEN + 3); k++) {
  1009.  
  1010.             t = TOKSYMS[n_TOKSYMS--];
  1011. #ifdef DEBUG
  1012.             if (trcopt)
  1013.                 fprintf (errfile, "take token off TOKSYMS (%s)\n", TOKSTR (t));
  1014. #endif
  1015.  
  1016.             if((kk=prs_check(sta_stack, TOKSYMS, n_TOKSYMS)) >= (MIN_LEN + 3)) {
  1017.                 /* changed +2 to +3, gcs */
  1018.                 /* delete k tokens */
  1019.  
  1020.                 /*    rightt := TOKENS(n_TOKENS - k + 1);
  1021.                  *  TOKENS(n_TOKENS - k + 1 ..) := [];
  1022.                  */
  1023.                 for (i = 1; i < k; i++)
  1024.                     TOKMINUS;
  1025.  
  1026.                 rightt = r_span (tokens[tokind]);
  1027.                 TOKMINUS;
  1028.  
  1029.                 syntax_err (LLOC (ERROR_TOKEN), &rightt, "Unexpected input");
  1030.  
  1031.                 return;
  1032.             }
  1033.  
  1034.             /* For now, ignore to conform with SETL (BEACON_SYMS is empty) 
  1035.              *    if (in_BEACON_SYMS (t))
  1036.               *   break;
  1037.              */
  1038.         }
  1039.  
  1040.         /* Try to resume the parse - perhaps with the inclusion of a sequence of
  1041.          * scope closers-  from some state on the state stack.    
  1042.          * After each attempt the current token is deleted.
  1043.          * To succeed on arbitrary input, some state must accept EOFT.
  1044.          */
  1045.  
  1046. #ifdef DEBUG
  1047.         if (trcopt)
  1048.             fprintf(errfile,"********** SECONDARY RECOVERY **********\n");
  1049. #endif
  1050.  
  1051.         nst = stack_size (sta_stack);
  1052.  
  1053.         while (1) {
  1054.             struct two_pool *sta_stack_copy;
  1055.  
  1056.             get_next(sec_check + 2);     /* ensure that there are ample */
  1057.  
  1058.             /*    TOKSYMS := [t(1) : t in TOKENS]; */
  1059.  
  1060.             i = 0;
  1061.             j = tokbottom;
  1062.  
  1063.             for (;;) {
  1064.                 TOKSYMS[i] = tokens[j] -> symbol;
  1065.                 if (j == tokind)
  1066.                     break;
  1067.                 j = (j + 1) % toksiz;
  1068.                 i++;
  1069.             }
  1070.  
  1071.             n_TOKSYMS = (toksiz + tokind - tokbottom) % toksiz;
  1072.  
  1073.             curtok = tokens[tokind];
  1074.  
  1075. #ifdef DEBUG
  1076.             if (trcopt) {
  1077.                 fprintf(errfile,"TRYING: %s\n",TOKSTR(TOKSYMS[n_TOKSYMS]) );
  1078.                 fprintf(errfile,
  1079.                   "\ttoksize = %d  tokbottom = %d  tokind = %d  curtok = %s\n",
  1080.                   toksiz,tokbottom,tokind,find_name(curtok) );
  1081.             }
  1082. #endif
  1083.  
  1084.             copystack (sta_stack, &sta_stack_copy, &nst);
  1085.  
  1086.             for (k = nst; k >= 1; k--) {
  1087.  
  1088.                 /* Try peeling stacks. */
  1089.  
  1090.                 /* Strip n_sta_stack - k - 1 elements off the state stack */
  1091.  
  1092.                 kk = stack_size (sta_stack_copy) - k;
  1093.  
  1094.                 /* while (--kk > 0)
  1095.                  *  sta_stack_copy = sta_stack_copy -> link;
  1096.                  */
  1097.  
  1098.                 if ( (kk=prs_check (sta_stack_copy, TOKSYMS, n_TOKSYMS)) >=
  1099.                   (sec_check + 2)) { /* (sec_check + 1)) */
  1100.                     /* Form the error message and quit the outer loop */
  1101.                     sprintf (err_msgs, "%s", err_message (k,curtok));
  1102. #ifdef DEBUG
  1103.                     if (trcopt)
  1104.                         fprintf(errfile,"prs_check succeeded for k = %d\n",k);
  1105. #endif
  1106.                     goto quit_loop_do;
  1107.                 }
  1108.  
  1109.                 /* Try closer recovery. */
  1110.  
  1111.                 /* Make a copy of the state stack for later restoration */
  1112.  
  1113.                 if (scope_recovery (k, 0, open_seq)) {
  1114.                     /* Form the error message and quit the outer loop */
  1115.                     sprintf (tmp_str, "%s", err_msgs);
  1116.                     sprintf (err_msgs, "%s -- %s", err_message(k,curtok),
  1117.                       tmp_str);
  1118. #ifdef DEBUG
  1119.                     if (trcopt)
  1120.                         fprintf(errfile,
  1121.                           "scope_recovery succeeded for k = %d\n",k);
  1122. #endif
  1123.  
  1124.                     goto quit_loop_do;
  1125.                 }
  1126.                 /* pop element of the state stack  */
  1127.                 sta_stack_copy = sta_stack_copy -> link;
  1128.  
  1129.                 closer_toksyms = NULL;
  1130.             }
  1131.  
  1132.             /* Get next token */
  1133.  
  1134. #ifdef IGNORE
  1135.             PREVTOK = tokens[tokind];
  1136.             /* This is a fix proposed by Sam Chin for cases when the entire
  1137.              * text is garbage. If there are tokens on the list of lookahead
  1138.              * tokens then take the token, otherwise, if not then take it from
  1139.              * the input stream. If while deleting the tokens an end of file
  1140.              * is reached, output the appropriate message and quit the
  1141.              * secondary recovery
  1142.              */
  1143.             curtok = NEXTTOK ;
  1144. #ifdef DEBUG
  1145.             if (trcopt)
  1146.                 fprintf(errfile,"curtok = %s\n",find_name(curtok));
  1147. #endif
  1148.             if (curtok->symbol == EOFT_SYM) {
  1149.                 sprintf(err_msgs,"End-of-file reached while trying to recover");
  1150.                 goto quit_loop_do ;
  1151.             }
  1152.  
  1153.             if (tokind >= MAX_LOOK_AHEAD) {
  1154.                 curtok = copytoken(tokens[tokind]) ;
  1155. #ifdef DEBUG
  1156.                 if (trcopt)
  1157.                     fprintf(errfile,"curtok updated to  %s\n",
  1158.                       find_name(curtok));
  1159. #endif
  1160.             }
  1161. #endif
  1162.  
  1163.             /* implement next_token macro (correctly), as done in SETL */
  1164.             PREVTOK = curtok;
  1165.             TOKMINUS;
  1166.             if ((toksiz + tokind - tokbottom + 1) % toksiz == 0)
  1167.                 tokens[tokbottom=(toksiz+tokbottom-1)%toksiz] = gettok();
  1168.  
  1169.             /* NEXTTOK; */
  1170.  
  1171.             /* copytoken (curtok, tokens[tokind]); */
  1172.  
  1173.         }
  1174.  
  1175. quit_loop_do: 
  1176.         ;            /* LABEL for goto */
  1177.  
  1178.  
  1179.         /* At this point we have recovered.    
  1180.          * Locate the range of the error.    
  1181.          */
  1182.  
  1183.  
  1184.         n_stack_del_syms = 0;
  1185.         if (nst > k     &&  k > 0  &&    prs_stack != NULL) {
  1186.             /* check for empty parse stack and k not zero (i.e. end of file) */
  1187.  
  1188.             /* stack_delete_syms :=
  1189.                 [PRS_STACK(t)(1) : t in [nps, nps - 1 .. k + 1]]; */
  1190.  
  1191.             /* nps = stack_count (prs_stack); */
  1192.             tmp_ps = prs_stack;
  1193.             stack_delete_syms =
  1194.               (int *) malloc ((unsigned) ((nst - k ) * sizeof (int)));
  1195.             /* stack_delete_syms = (int *) malloc ((k + 1) * sizeof (int)); */
  1196.             for (t = nst; t >= k + 1; t--) {
  1197.                 stack_delete_syms[n_stack_del_syms++] = tmp_ps -> symbol;
  1198.                 tmp_ps = tmp_ps -> prev;
  1199.             }
  1200.  
  1201.             leftt = l_span (tmp_ps);
  1202.  
  1203.             /*         PRS_STACK(k + 1 .. ) := [];
  1204.              *                STA_STACK(k + 1 .. ) := [];    
  1205.              */
  1206.  
  1207.             kk = stack_size (sta_stack) - k;
  1208.             while ( kk-- > 0) {
  1209.                 sta_stack = sta_stack -> link;
  1210.                 prs_stack = prs_stack -> prev;
  1211.             }
  1212.         }
  1213.         else
  1214.             leftt = l_span (ERROR_TOKEN);
  1215.  
  1216.  
  1217.         /* Form error location. */
  1218.  
  1219.         /*
  1220.          *    Check whether 
  1221.          *        stack_delete_syms = 
  1222.          *            TOKSYMS(#TOKSYMS - #stack_del_syms + 1 ..  #stack_del_syms)
  1223.          *
  1224.          *    Assume equal and check element by element
  1225.          */
  1226.  
  1227.         equal = 1;
  1228.         for (j = n_stack_del_syms - 1 , k = n_TOKSYMS ;
  1229.           ((j >= 0) && (equal)) ; k--, j--)
  1230.             equal = equal && (stack_delete_syms[j] == TOKSYMS[k]);
  1231.  
  1232.         if ((n_stack_del_syms != 0) && (n_stack_del_syms <= n_TOKSYMS) && equal)
  1233.         {
  1234.             /* PRSERR_LOC = loc_range(LLOC(ERROR_TOKEN), LLOC(TOKENS[(tokind -
  1235.                 * n_stack_del_syms + 1) % toksiz] ), RLOC(ERROR_TOKEN));
  1236.              * for now just print the spans
  1237.              */
  1238.             syntax_err (LLOC (ERROR_TOKEN), RLOC (ERROR_TOKEN), err_msgs);
  1239.         }
  1240.         else {
  1241.             /* PRSERR_LOC = 
  1242.               *  loc_range(LLOC(leftt), LLOC(PREVTOK), RLOC(ERROR_TOKEN));
  1243.               *  for now just print the spans
  1244.              */
  1245.             syntax_err (&leftt, RLOC (ERROR_TOKEN), err_msgs);
  1246.         }
  1247.  
  1248.         /* If the secondary recovery involves a scope recovery, insert the
  1249.          * closer tokens.    
  1250.          */
  1251.  
  1252.         if (closer_toksyms != NULL) {
  1253.             /* TOKENS +:= [[t, t, top(PREVTOK)] : t in CLOSER_TOKSYMS]; */
  1254.             for(tmp_tp =closer_toksyms; tmp_tp != NULL; tmp_tp = tmp_tp -> link)
  1255.             {
  1256.                 ADDTOTOP (PRSALLOC());
  1257.                 tokens[tokind] -> symbol = tmp_tp -> val.state;
  1258.                 tokens[tokind] -> ptr.token = TOKALLOC ();
  1259.                 tokens[tokind] -> ptr.token -> index = tmp_tp -> val.state;
  1260.                 tokens[tokind] -> ptr.token -> loc = PREVTOK -> ptr.token ->loc;
  1261.             }
  1262.         }
  1263.  
  1264.         return;
  1265.     }
  1266. }                /* End of Procedure prserr */
  1267.  
  1268. static void get_poss_tok()                    /*;get_poss_tok*/
  1269. {
  1270.     struct two_pool *temp_sta_stack; /* Points to saved copy of state stack    */
  1271.     struct two_pool *act_sta = NULL ; /* Stored list of acceptable actions    */
  1272.     int    ss = sta_stack->val.state ;    /* The top of the state stack            */
  1273.     struct two_pool *tmp_tp ;            /* utility variables            */
  1274.     struct two_pool *tmp ;
  1275.     short    red,dr ;
  1276.     int    n ,n_temp_sta_stack ;
  1277.  
  1278.     /* Get the tokens that are acceptable to the top state on the stack.  */
  1279.  
  1280.     copystack(sta_stack,&temp_sta_stack,&n_temp_sta_stack);
  1281.  
  1282.     while ((dr = def_action[ss - 1]) != 0) {
  1283.         tmp = TALLOC() ;        /* act_sta with := ss    */
  1284.         tmp->val.state = ss ;
  1285.         tmp->link = act_sta ;
  1286.         act_sta = tmp ;
  1287.  
  1288.         red = dr - NUM_STATES - 1 ;
  1289.  
  1290.         /*    Strip "rhslen[red]" elements from the temp_sta_stack */
  1291.         n = rhslen[red] ;
  1292.         if(!n) {
  1293.             tmp = TALLOC() ;
  1294.             tmp->link = temp_sta_stack ;
  1295.             temp_sta_stack = tmp ;
  1296.         }
  1297.         else if( n > 1 ) {
  1298.             while( --n > 1 )
  1299.                 temp_sta_stack = temp_sta_stack->link ;
  1300.             tmp = temp_sta_stack ;
  1301.             temp_sta_stack = temp_sta_stack->link ;
  1302.         }
  1303.         else if (n < 0)
  1304.             break ;
  1305.         temp_sta_stack->val.state =    
  1306.           action((int)(temp_sta_stack->link->val.state),lhs[red]);
  1307.         ss = temp_sta_stack->val.state ;
  1308.     }
  1309.  
  1310.     tmp = TALLOC() ;
  1311.     tmp->val.state = ss ;
  1312.     tmp->link = act_sta ;
  1313.     act_sta = tmp ;
  1314.  
  1315.  
  1316.     /* 
  1317.      * POSS_TOK := +/{ACTION_TOKENS(s) : s in act_sta};                
  1318.      * Since ACTION_TOKENS(s) is a set of numbers, for each s we must
  1319.      * loop over the set, adding the values to the list POSS_TOK
  1320.      */
  1321.     POSS_TOK = NULL ;
  1322.     while (act_sta != NULL) {
  1323.         int a ;
  1324.  
  1325.         for(a = ACTION_TOKENS_INDEX[(int)(act_sta->val.state) - 1] ;
  1326.           a <= (ACTION_TOKENS_INDEX[(int)(act_sta->val.state)] - 1) ; a ++ )
  1327.         {
  1328.             /* Add ACTION_TOKENS(a) to the list */
  1329.             tmp_tp = TALLOC() ;
  1330.             tmp_tp->link = POSS_TOK ;
  1331.             tmp_tp->val.state = ACTION_TOKENS[a] ;
  1332.             POSS_TOK = tmp_tp ;
  1333.         }
  1334.         act_sta = act_sta->link ;
  1335.     }
  1336. }
  1337.  
  1338. static void get_next(int k)                /*;get_next*/
  1339. {
  1340.     /* This procedure ensures that tokens contains at least k tokens.  
  1341.      * Note that tokind always points to the next token, so that the
  1342.      * array must be read in in reverse order
  1343.      */
  1344.  
  1345.     int i;
  1346.  
  1347.     /* First check if this is the first time, and if so allocate space for
  1348.      * tokens.
  1349.      */
  1350.  
  1351.     if (tokind == -1) {
  1352.         tokens =
  1353.           (struct prsstack **)malloc((unsigned)(2*k*sizeof(struct prsstack *)));
  1354.         toksiz = 2 * k;
  1355.     }
  1356.  
  1357.     /* for now only put in k-1 tokens, since the current token has to be
  1358.      * inserted.
  1359.      */
  1360.     for (i = k - ((toksiz + (tokind - tokbottom + 1)) % toksiz); i>0 ; i--) {
  1361.         tokbottom = (toksiz + tokbottom - 1) % toksiz;
  1362.         tokens[tokbottom] = gettok();
  1363.     }
  1364.     if (tokind == -1)
  1365.         tokind = toksiz - 1;
  1366. }
  1367.